﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Media.Imaging;
using System.IO;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.ComponentModel;
using System.Windows.Threading;
using System.Windows.Interop;

namespace OVS_Tools
{
    public class ImageHelper
    {

        public static Bitmap BitmapImageToBitmap(BitmapImage bitmapImage)
        {
            using (MemoryStream outStream = new MemoryStream())
            {
                BitmapEncoder enc = new BmpBitmapEncoder();
                enc.Frames.Add(BitmapFrame.Create(bitmapImage));
                enc.Save(outStream);
                System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);
                return new Bitmap(bitmap);
            }
        }

        public static BitmapImage BitmapToBitmapImage(Bitmap bitmap)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                bitmap.Save(ms, ImageFormat.Png);
                ms.Position = 0;
                BitmapImage bi = new BitmapImage();
                bi.BeginInit();
                bi.StreamSource = ms;
                bi.EndInit();

                return bi;
            }
        }

        public static ImageSource BitmapToImageSource(Bitmap bitmap)
        {
            //ImageSourceConverter c = new ImageSourceConverter();
            //return (ImageSource)c.ConvertFrom(bitmap);

            return BitmapExtensions.ToImageSource(bitmap);
        }

        //public static Bitmap ImageSourceToBitmap(ImageSource imageSource)
        //{
        //    ImageSourceConverter c = new ImageSourceConverter();
        //    return imageSource.get



        public static System.Drawing.Bitmap BitmapSourceToBitmap(BitmapSource srs)
        {
            System.Drawing.Bitmap btm = null;
            int width = srs.PixelWidth;
            int height = srs.PixelHeight;
            int stride = width * ((srs.Format.BitsPerPixel + 7) / 8);
            IntPtr ptr = Marshal.AllocHGlobal(height * stride);
            srs.CopyPixels(new Int32Rect(0, 0, width, height), ptr, height * stride, stride);
            btm = new System.Drawing.Bitmap(width, height, stride, System.Drawing.Imaging.PixelFormat.Format1bppIndexed, ptr);
            return btm;
        }

        ///// <summary>
        ///// Converts a <see cref="System.Drawing.Image"/> into a WPF <see cref="BitmapSource"/>.
        ///// </summary>
        ///// <param name="source">The source image.</param>
        ///// <returns>A BitmapSource</returns>
        //public static BitmapSource ToBitmapSource(this System.Drawing.Image source)
        //{
        //    System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(source);

        //    var bitSrc = bitmap.ToBitmapSource();

        //    bitmap.Dispose();
        //    bitmap = null;

        //    return bitSrc;
        //}

      

        public static BitmapSource CreateBitmapSourceFromBitmap(Bitmap bitmap)
        {
            //if (bitmap == null)
            //    throw new ArgumentNullException("bitmap");

            //if (Application.Current.Dispatcher == null)
            //    return null; // Is it possible?

            //try
            //{
            //    using (MemoryStream memoryStream = new MemoryStream())
            //    {
            //        // You need to specify the image format to fill the stream. 
            //        // I'm assuming it is PNG
            //        bitmap.Save(memoryStream, ImageFormat.Png);
            //        memoryStream.Seek(0, SeekOrigin.Begin);

            //        // Make sure to create the bitmap in the UI thread
            //        if (InvokeRequired)
            //            return (BitmapSource)Application.Current.Dispatcher.Invoke(
            //                new Func<Stream, BitmapSource>(CreateBitmapSourceFromBitmap),
            //                DispatcherPriority.Normal,
            //                memoryStream);
            //        bitmap.Dispose();

            //        return CreateBitmapSourceFromBitmap(memoryStream);
            //    }
            //}
            //catch (Exception)
            //{
            //    return null;
            //}

            return BitmapExtensions.ToImageSource(bitmap) as BitmapSource;
        }

        private static bool InvokeRequired
        {
            get { return Dispatcher.CurrentDispatcher != Application.Current.Dispatcher; }
        }

        //private static BitmapSource CreateBitmapSourceFromBitmap(Stream stream)
        //{
        //    BitmapDecoder bitmapDecoder = BitmapDecoder.Create(
        //        stream,
        //        BitmapCreateOptions.PreservePixelFormat,
        //        BitmapCacheOption.OnLoad);

        //    // This will disconnect the stream from the image completely...
        //    WriteableBitmap writable = new WriteableBitmap(bitmapDecoder.Frames.Single());
        //    writable.Freeze();

        //    return writable;
        //}

        public static Bitmap GetBitmap(BitmapSource source)
        {
            Bitmap bmp = new Bitmap(
              source.PixelWidth,
              source.PixelHeight,
              System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
            BitmapData data = bmp.LockBits(
              new Rectangle(System.Drawing.Point.Empty, bmp.Size),
              ImageLockMode.WriteOnly,
              System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
            source.CopyPixels(
              Int32Rect.Empty,
              data.Scan0,
              data.Height * data.Stride,
              data.Stride);
            bmp.UnlockBits(data);
            return bmp;
        }
    }

    public static class BitmapExtensions
    {
        public static ImageSource ToImageSource(this Bitmap bitmap)
        {
            var hbitmap = bitmap.GetHbitmap();
            try
            {
                var imageSource = Imaging.CreateBitmapSourceFromHBitmap(hbitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(bitmap.Width, bitmap.Height));

                return imageSource;
            }
            finally
            {
                NativeMethods.DeleteObject(hbitmap);
            }
        }
    }

    public static class NativeMethods
    {
        [DllImport("gdi32")]
        public static extern int DeleteObject(IntPtr hObject);
    }
}
